package com.gitee.wsl.ext.bitcode

import com.gitee.wsl.ext.base.toInt

/** Replaces [this] bits from [offset] to [offset]+[count] with [value] and returns the result of doing such replacement */
 fun Int.insert(value: Int, offset: Int, count: Int): Int {
    val mask = count.mask() shl offset
    val ovalue = (value shl offset) and mask
    return (this and mask.inv()) or ovalue
}

 fun Int.insertNoClear(value: Int, offset: Int, count: Int): Int {
    return this or ((value and count.mask()) shl offset)
}

 fun Int.insert1(value: Int, offset: Int): Int = insertMask(value, offset, 0b1)
 fun Int.insert2(value: Int, offset: Int): Int = insertMask(value, offset, 0b11)
 fun Int.insert3(value: Int, offset: Int): Int = insertMask(value, offset, 0b111)
 fun Int.insert4(value: Int, offset: Int): Int = insertMask(value, offset, 0b1111)
 fun Int.insert5(value: Int, offset: Int): Int = insertMask(value, offset, 0b11111)
 fun Int.insert6(value: Int, offset: Int): Int = insertMask(value, offset, 0b111111)
 fun Int.insert7(value: Int, offset: Int): Int = insertMask(value, offset, 0b1111111)
 fun Int.insert8(value: Int, offset: Int): Int = insertMask(value, offset, 0b11111111)
 fun Int.insert9(value: Int, offset: Int): Int = insertMask(value, offset, 0b111111111)
 fun Int.insert10(value: Int, offset: Int): Int = insertMask(value, offset, 0b1111111111)
 fun Int.insert11(value: Int, offset: Int): Int = insertMask(value, offset, 0b11111111111)
 fun Int.insert12(value: Int, offset: Int): Int = insertMask(value, offset, 0b111111111111)
 fun Int.insert13(value: Int, offset: Int): Int = insertMask(value, offset, 0b1111111111111)
 fun Int.insert14(value: Int, offset: Int): Int = insertMask(value, offset, 0b11111111111111)
 fun Int.insert15(value: Int, offset: Int): Int = insertMask(value, offset, 0b111111111111111)
 fun Int.insert16(value: Int, offset: Int): Int = insertMask(value, offset, 0b1111111111111111)
 fun Int.insert17(value: Int, offset: Int): Int = insertMask(value, offset, 0b11111111111111111)
 fun Int.insert18(value: Int, offset: Int): Int = insertMask(value, offset, 0b111111111111111111)
 fun Int.insert19(value: Int, offset: Int): Int = insertMask(value, offset, 0b1111111111111111111)
 fun Int.insert20(value: Int, offset: Int): Int = insertMask(value, offset, 0b11111111111111111111)
 fun Int.insert21(value: Int, offset: Int): Int = insertMask(value, offset, 0b111111111111111111111)
 fun Int.insert22(value: Int, offset: Int): Int = insertMask(value, offset, 0b1111111111111111111111)
 fun Int.insert23(value: Int, offset: Int): Int = insertMask(value, offset, 0b11111111111111111111111)
 fun Int.insert24(value: Int, offset: Int): Int = insertMask(value, offset, 0b111111111111111111111111)
 fun Int.insert25(value: Int, offset: Int): Int = insertMask(value, offset, 0b1111111111111111111111111)
 fun Int.insert26(value: Int, offset: Int): Int = insertMask(value, offset, 0b11111111111111111111111111)
 fun Int.insert27(value: Int, offset: Int): Int = insertMask(value, offset, 0b111111111111111111111111111)
 fun Int.insert28(value: Int, offset: Int): Int = insertMask(value, offset, 0b1111111111111111111111111111)
 fun Int.insert29(value: Int, offset: Int): Int = insertMask(value, offset, 0b11111111111111111111111111111)
 fun Int.insert30(value: Int, offset: Int): Int = insertMask(value, offset, 0b111111111111111111111111111111)
 fun Int.insert31(value: Int, offset: Int): Int = insertMask(value, offset, 0b1111111111111111111111111111111)
 fun Int.insert32(value: Int, offset: Int): Int = insertMask(value, offset, -1)

/** Fast Insert: do not clear bits, assume affecting bits are 0 */
 fun Int.finsert(value: Int, offset: Int): Int = this or (value shl offset)
 fun Int.finsert24(value: Int, offset: Int): Int = this or ((value and 0xFFFFFF) shl offset)
 fun Int.finsert16(value: Int, offset: Int): Int = this or ((value and 0xFFFF) shl offset)
 fun Int.finsert12(value: Int, offset: Int): Int = this or ((value and 0xFFF) shl offset)
 fun Int.finsert8(value: Int, offset: Int): Int = this or ((value and 0xFF) shl offset)
 fun Int.finsert7(value: Int, offset: Int): Int = this or ((value and 0b1111111) shl offset)
 fun Int.finsert6(value: Int, offset: Int): Int = this or ((value and 0b111111) shl offset)
 fun Int.finsert5(value: Int, offset: Int): Int = this or ((value and 0b11111) shl offset)
 fun Int.finsert4(value: Int, offset: Int): Int = this or ((value and 0b1111) shl offset)
 fun Int.finsert3(value: Int, offset: Int): Int = this or ((value and 0b111) shl offset)
 fun Int.finsert2(value: Int, offset: Int): Int = this or ((value and 0b11) shl offset)
 fun Int.finsert1(value: Int, offset: Int): Int = this or ((value and 0b1) shl offset)
 fun Int.finsert(value: Boolean, offset: Int): Int = finsert(value.toInt(), offset)

inline fun Int.insertMask(value: Int, offset: Int, mask: Int): Int {
    return (this and (mask shl offset).inv()) or ((value and mask) shl offset)
}
/** Replaces 1 bit at [offset] with [value] and returns the result of doing such replacement */
 fun Int.insert(value: Boolean, offset: Int): Int {
    val bits = (1 shl offset)
    return if (value) this or bits else this and bits.inv()
}

 fun Int.insertScaled(value: Int, offset: Int, count: Int, scale: Int): Int = insert((value * count.mask()) / scale, offset, count)
 fun Int.insertScaledFF(value: Int, offset: Int, count: Int): Int = if (count == 0) this else this.insertScaled(value, offset, count, 0xFF)
/** Extracts [count] at [offset] from [this] [Int] and convert the possible values into the range 0.0..1.0 */
 fun Int.insertScaledf01(value: Float, offset: Int, count: Int): Int = this.insert((value.coerceIn(0f, 1f) * offset.mask()).toInt(), offset, count)
